/* Copyright (c) 2006, 2009, Carl Burch. License information is located in the
 * com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */
 
package com.cburch.logisim.analyze.gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.cburch.logisim.analyze.model.AnalyzerModel;
import com.cburch.logisim.gui.menu.LogisimMenuBar;
import com.cburch.logisim.util.Strings;
import com.cburch.logisim.Locale.LocaleListener;
import com.cburch.logisim.Locale.LocaleManager;

public class Analyzer extends JFrame {
    // used by circuit analysis to select the relevant tab automatically.
    public static final int INPUTS_TAB = 0;
    public static final int OUTPUTS_TAB = 1;
    public static final int TABLE_TAB = 2;
    public static final int EXPRESSION_TAB = 3;
    public static final int MINIMIZED_TAB = 4;
    
    private class MyListener implements LocaleListener {
        public void localeChanged() {
            Analyzer.this.setTitle(Strings.get("analyzerWindowTitle", Strings.analyzeSource));
            tabbedPane.setTitleAt(INPUTS_TAB, Strings.get("inputsTab", Strings.analyzeSource));
            tabbedPane.setTitleAt(OUTPUTS_TAB, Strings.get("outputsTab", Strings.analyzeSource));
            tabbedPane.setTitleAt(TABLE_TAB, Strings.get("tableTab", Strings.analyzeSource));
            tabbedPane.setTitleAt(EXPRESSION_TAB, Strings.get("expressionTab", Strings.analyzeSource));
            tabbedPane.setTitleAt(MINIMIZED_TAB, Strings.get("minimizedTab", Strings.analyzeSource));
            tabbedPane.setToolTipTextAt(INPUTS_TAB, Strings.get("inputsTabTip", Strings.analyzeSource));
            tabbedPane.setToolTipTextAt(OUTPUTS_TAB, Strings.get("outputsTabTip", Strings.analyzeSource));
            tabbedPane.setToolTipTextAt(TABLE_TAB, Strings.get("tableTabTip", Strings.analyzeSource));
            tabbedPane.setToolTipTextAt(EXPRESSION_TAB, Strings.get("expressionTabTip", Strings.analyzeSource));
            tabbedPane.setToolTipTextAt(MINIMIZED_TAB, Strings.get("minimizedTabTip", Strings.analyzeSource));
            buildCircuit.setText(Strings.get("buildCircuitButton", Strings.analyzeSource));
            inputsPanel.localeChanged();
            outputsPanel.localeChanged();
            truthTablePanel.localeChanged();
            expressionPanel.localeChanged();
            minimizedPanel.localeChanged();
            buildCircuit.localeChanged();
        }
    }
    
    private class EditListener implements ActionListener, ChangeListener {
        private void register(LogisimMenuBar menubar) {
            menubar.addActionListener(LogisimMenuBar.CUT, this);
            menubar.addActionListener(LogisimMenuBar.COPY, this);
            menubar.addActionListener(LogisimMenuBar.PASTE, this);
            menubar.addActionListener(LogisimMenuBar.DELETE, this);
            menubar.addActionListener(LogisimMenuBar.SELECT_ALL, this);
            tabbedPane.addChangeListener(this);
            enableItems(menubar);
        }
        
        public void actionPerformed(ActionEvent e) {
            Object src = e.getSource();
            Component c = tabbedPane.getSelectedComponent();
            if(c instanceof JScrollPane) {
                c = ((JScrollPane) c).getViewport().getView();
            }
            if(!(c instanceof TabInterface)) return;
            TabInterface tab = (TabInterface) c;
            if(src == LogisimMenuBar.CUT) {
                tab.copy();
                tab.delete();
            } else if(src == LogisimMenuBar.COPY) {
                tab.copy();
            } else if(src == LogisimMenuBar.PASTE) {
                tab.paste();
            } else if(src == LogisimMenuBar.DELETE) {
                tab.delete();
            } else if(src == LogisimMenuBar.SELECT_ALL) {
                tab.selectAll();
            }
        }
        
        private void enableItems(LogisimMenuBar menubar) {
            Component c = tabbedPane.getSelectedComponent();
            if(c instanceof JScrollPane) {
                c = ((JScrollPane) c).getViewport().getView();
            }
            boolean support = c instanceof TabInterface;
            menubar.setEnabled(LogisimMenuBar.CUT, support);
            menubar.setEnabled(LogisimMenuBar.COPY, support);
            menubar.setEnabled(LogisimMenuBar.PASTE, support);
            menubar.setEnabled(LogisimMenuBar.DELETE, support);
            menubar.setEnabled(LogisimMenuBar.SELECT_ALL, support);
        }

        public void stateChanged(ChangeEvent e) {
            enableItems((LogisimMenuBar) getJMenuBar());
        }
    }
    
    private MyListener myListener = new MyListener();
    private EditListener editListener = new EditListener();
    private AnalyzerModel model = new AnalyzerModel();
    private JTabbedPane tabbedPane = new JTabbedPane();
    
    private VariableTab inputsPanel;
    private VariableTab outputsPanel;
    private TableTab truthTablePanel;
    private ExpressionTab expressionPanel;
    private MinimizedTab minimizedPanel;
    private BuildCircuitButton buildCircuit;
    
    Analyzer() {
        inputsPanel = new VariableTab(model.getInputs());
        outputsPanel = new VariableTab(model.getOutputs());
        truthTablePanel = new TableTab(model.getTruthTable());
        expressionPanel = new ExpressionTab(model);
        minimizedPanel = new MinimizedTab(model);
        buildCircuit = new BuildCircuitButton(this, model);

        truthTablePanel.addMouseListener(new TruthTableMouseListener());
        
        tabbedPane = new JTabbedPane();
        addTab(INPUTS_TAB, inputsPanel);
        addTab(OUTPUTS_TAB, outputsPanel);
        addTab(TABLE_TAB, truthTablePanel);
        addTab(EXPRESSION_TAB, expressionPanel);
        addTab(MINIMIZED_TAB, minimizedPanel);
        
        Container contents = getContentPane();
        JPanel vertStrut = new JPanel(null);
        vertStrut.setPreferredSize(new Dimension(0, 300));
        JPanel horzStrut = new JPanel(null);
        horzStrut.setPreferredSize(new Dimension(450, 0));
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(buildCircuit);
        contents.add(vertStrut, BorderLayout.WEST);
        contents.add(horzStrut, BorderLayout.NORTH);
        contents.add(tabbedPane, BorderLayout.CENTER);
        contents.add(buttonPanel, BorderLayout.SOUTH);
        
        DefaultRegistry registry = new DefaultRegistry(getRootPane());
        inputsPanel.registerDefaultButtons(registry);
        outputsPanel.registerDefaultButtons(registry);
        expressionPanel.registerDefaultButtons(registry);
        
        LocaleManager.addLocaleListener(myListener);
        myListener.localeChanged();
        
        LogisimMenuBar menubar = new LogisimMenuBar(this, null);
        setJMenuBar(menubar);
        editListener.register(menubar);
    }
    
    private void addTab(int index, final JComponent comp) {
        final JScrollPane pane = new JScrollPane(comp,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        if(comp instanceof TableTab) {
            pane.setVerticalScrollBar(((TableTab) comp).getVerticalScrollBar());
        }
        pane.addComponentListener(new ComponentListener() {
            public void componentResized(ComponentEvent event) {
                int width = pane.getViewport().getWidth();
                comp.setSize(new Dimension(width, comp.getHeight()));
            }

            public void componentMoved(ComponentEvent arg0) { }
            public void componentShown(ComponentEvent arg0) { }
            public void componentHidden(ComponentEvent arg0) { }
        });
        tabbedPane.insertTab("Untitled", null, pane, null, index);
    }
    
    public AnalyzerModel getModel() {
        return model;
    }
    
    public void setSelectedTab(int index) {
        tabbedPane.setSelectedIndex(index);
    }
    
    public static void main(String[] args) {
        Analyzer frame = new Analyzer();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}
